<template>
    <a-layout>
        <a-layout-sider width="350" style="background: #fff; height: calc(100vh - 60px); overflow-y: scroll; overflow-x: hidden;">
            <a-button type="default">+</a-button>
            <!-- <a-menu
                id="dddddd"
                v-model:openKeys="openKeys"
                v-model:selectedKeys="selectedKeys"
                style="width: 256px"
                mode="inline"
                :items="items"
                @click="handleClick"
            >
          </a-menu> -->

          <!-- <a-directory-tree
            v-model:expandedKeys="openKeys"
            v-model:selectedKeys="selectedKeys"
            multiple
            :tree-data="items"
          ></a-directory-tree> -->

          <a-tree
            v-model:expandedKeys="openKeys" 
            block-node
            v-model:selectedKeys="selectedKeys" :tree-data="items">
            <template #title="{ key: treeKey, title, type }">
              <a-dropdown :trigger="['contextmenu']">
                <div><folder-open-outlined v-if="type === 'directory'" /><FileMarkdownOutlined v-else /> 
                {{ title }}</div>
                <template #overlay>
                  <a-menu @click="({ key: menuKey }) => onContextMenuClick(treeKey, menuKey)">
                    <a-menu-item key="1">1st menu item</a-menu-item>
                    <a-menu-item key="2">2nd menu item</a-menu-item>
                    <a-menu-item key="3">3rd menu item</a-menu-item>
                  </a-menu>
                </template>
              </a-dropdown>
            </template>
          </a-tree>
        </a-layout-sider>
        <a-layout style="">
            <a-layout-content
                :style="{ background: '#fff', margin: 0, minHeight: '280px', zIndex: 999}"
            >
                <div id="editor"></div>
            </a-layout-content>
        </a-layout>
        <div class="sidebar" id="sidebar">
          <ol>
          </ol>
        </div>
    </a-layout>
</template>
<script setup>
import { onMounted, reactive, ref, watch, h } from 'vue'

import Editor from '@toast-ui/editor';
import '@toast-ui/editor/dist/toastui-editor.css'; // Editor's Style
import '@toast-ui/editor/dist/i18n/zh-cn';

import http from '@/utils/http';

import 'prismjs/themes/prism.css';
import '@toast-ui/editor-plugin-code-syntax-highlight/dist/toastui-editor-plugin-code-syntax-highlight.css';

// import codeSyntaxHighlight from '@toast-ui/editor-plugin-code-syntax-highlight';
import codeSyntaxHighlight from '@toast-ui/editor-plugin-code-syntax-highlight/dist/toastui-editor-plugin-code-syntax-highlight-all.js';


import { FolderOpenOutlined, FileMarkdownOutlined } from '@ant-design/icons-vue';
import { isLeaf } from 'ant-design-vue/es/vc-cascader/utils/commonUtil';

// 定义一个防抖函数
function debounce(func, wait) {
  let timeout;
  return function() {
    const context = this;
    const args = arguments;
    clearTimeout(timeout);
    timeout = setTimeout(function() {
      func.apply(context, args);
    }, wait);
  };
}
// 使用防抖函数
const debouncedUpdateFile = debounce(function() {
  // handleFileContentChange();
  const markdownStr2 = editor.getMarkdown();

  renderMarkdownHeadersToDOM('sidebar');

  http.post('/updateFile', {
    filePath: formState.filePath,
    content: markdownStr2
  }).then((res) => {
    console.log(res);
  }).catch((err) => {
    console.error(err); // 错误应该使用 console.error 打印
  });
}, 1000); // 调整等待时间为 500 毫秒

const formState = reactive({
  htmlStr: '',
  filePath: ''
});

const handleFileContentChange = (e) => {
  // 查找#editor标签下内容中的http或https地址，自动添加target="_blank"
  document.querySelectorAll('#editor a').forEach(a => {
    const href = a.getAttribute('href');
    if (href.startsWith('http') || href.startsWith('https')) {
      a.setAttribute('target', '_blank');
    }
  });
  // 查找h1到h7的标题构造为目录，放入sidebar内，点击目录跳转至对应位置。已知原标题没有id
  const hs = document.querySelectorAll('#editor h1, #editor h2, #editor h3, #editor h4, #editor h5, #editor h6');
  const sidebar = document.querySelector('.sidebar');
  

  let i=0;
  const ol = document.createElement('ol');
  hs.forEach(h => {
    // 标题原位置要加上id
    const id = "title-" + i++;
    h.id = id;
    // 从h1到h7应该有层级，最外层也在ol内
    const li = document.createElement('li');
    const a = document.createElement('a');
    a.href = '#' + id;
    a.textContent = h.textContent;
    li.appendChild(a);
    ol.appendChild(li);
  });
  // 替换ol
  document.querySelector('.sidebar')?.replaceChild(ol, document.querySelector('.sidebar ol'));
};
function renderMarkdownHeadersToDOM(targetElementId) {
  const elements = editor.getEditorElements()
  console.log(elements);
  const { mdEditor, mdPreview, wwEditor } = editor.getEditorElements();  
  
  // 获取HTML内容  
  let mdEditorHtml = mdEditor.innerHTML;  
  let wwEditorHtml = wwEditor.innerHTML;  

  // 使用DOMParser来解析HTML字符串  
  const parser = new DOMParser();  
  const doc = parser.parseFromString(wwEditorHtml, 'text/html');  

  // 假设我们只对<h1>到<h6>感兴趣  
  const titles = doc.querySelectorAll('h1, h2, h3, h4, h5, h6');  

  // 创建一个新的元素来存储标题列表  
  const titlesList = document.createElement('ul');  

  titles.forEach((title, index) => {  
      // 为标题添加ID（这里简单使用index，实际中可能需要更复杂的逻辑以避免重复）  
      title.id = `title-${index}`;  

      // 创建列表项并添加到列表中  
      const listItem = document.createElement('li');  
      // listItem.textContent = title.textContent; // 只获取文本内容  
      // listItem.appendChild(document.createTextNode(' - ')); // 添加分隔符  
      const anchor = document.createElement('a');  
      anchor.href = `#${title.id}`; // 创建锚点链接  
      anchor.textContent = `${title.textContent}`; // 修改链接文本  
      listItem.appendChild(anchor);  

      titlesList.appendChild(listItem);  
  });  

  // 将标题列表添加到指定的节点  
  document.getElementById(targetElementId).replaceChildren(titlesList);  
}
// const markdownStr = '';
// 初始化toastedir编辑器
let editor;
// 把onMounted中内容抽到函数中
const initEditor = (markdownStr) => {
  if (editor) {
    editor.destroy();
  }
  editor = new Editor({
      el: document.querySelector('#editor'),
      height: '100%',
      initialEditType: 'wysiwyg',
      previewStyle: 'vertical',
      language: 'zh-CN',
      initialValue: markdownStr,
      plugins: [codeSyntaxHighlight]
    });
  // handleFileContentChange();
    renderMarkdownHeadersToDOM('sidebar');
    // editor.getMarkdown();
    
    // 监听toastedir编辑器内容变化
    // 监听编辑器内容变化，并使用防抖函数限制更新频率
    editor.on('change', debouncedUpdateFile);
    editor.on('keyup', (editorType, e) => {
      // console.log('keyup', editorType, e);
      // 输出编辑器本区块本行的内容
      console.log(editor.getRangeInfoOfNode());
      // 根据range输出当前行的内容
      const rangeInfo = editor.getRangeInfoOfNode();
      if (rangeInfo) {
        const { range, type } = rangeInfo;
        // 根据range输出当前行的内容
        const currentLineContent = editor.getSelectedText(range[0], range[1]);
        console.log(`当前行内容：${currentLineContent}`);
      }
    });
};
onMounted(() => {
  
});


// const handleClick = e => {
//   if (editor) {
//     console.log(editor)
//   } else {
//     alert('编辑器未初始化')
//   }
//   console.log('click', e);
//   http.get('/fileContent?filePath=' + baseDir + e.key).then((res) => {
//     console.log(res.data)
//     editor.mdEditor.setMarkdown(res.data.content)
//   })
// };

const handleClick = async (e) => {
  console.log('click', e);
  formState.filePath = e.key
  try {
    const response = await http.get('/fileContent?filePath=' + baseDir + e.key);
    const content = response.data.content;
    console.log(content);
    initEditor(content);
    // if (editor) {
    // } else {
    //   alert('编辑器未初始化');
    // }
  } catch (error) {
    console.error('Error fetching file content:', error);
  }
};


let selectedKeys = ref([]);
let openKeys = ref([]);

const handleClick2 = async (e) => {
  console.log('click', e);
  // formState.filePath = baseDir + e.key
  try {
    const response = await http.get('/fileContent?filePath=' + e.key);
    const content = response.data.content;
    // if (editor) {
    //   editor.setMarkdown(content, false); // 使用正确的editor实例方法来设置Markdown
    // } else {
    //   alert('编辑器未初始化');
    // }
    initEditor(content);
  } catch (error) {
    console.error('Error fetching file content:', error);
  }
};
watch(openKeys, val => {
  console.log('openKeys', val);
});
function findNodeByKey(nodes, key) {  
    for (let i = 0; i < nodes.length; i++) {  
        if (nodes[i].key === key) {  
            // 如果当前节点就是我们要找的节点，直接返回它  
            return nodes[i];  
        }  
  
        // 如果当前节点不是我们要找的节点，则递归地在其子节点中查找  
        if (nodes[i].children && nodes[i].children.length > 0) {  
            const result = findNodeByKey(nodes[i].children, key);  
            if (result) {  
                return result; // 如果在子节点中找到了匹配的节点，则返回它  
            }  
        }  
    }  
  
    // 如果没有找到匹配的节点，则返回null或undefined（这里返回null）  
    return null;  
}  
watch(selectedKeys, (e) => {
  console.log('selectedKeys', selectedKeys, e);
  if (selectedKeys.value.length > 0) {
    const selectedKey = selectedKeys.value[0];
    formState.filePath = selectedKey
    // 获取当前树中当前子节点的信息
    const selectedItem = findNodeByKey(items, selectedKey)

    if (selectedItem && selectedItem.type === 'directory') {
      // 如果选中的是分组，则展开该分组
      // openKeys.value = [selectedKey];
    } else {
      // 如果选中的是文件，则打开文件
      // selectedKeys = [selectedKey]
      handleClick2(selectedItem);
    }
  }
})
// function getItem(label, key, children, icon, type) {
//   // 子节点也要渲染和点击
//   return {
//     key,
//     icon,
//     children,
//     label,
//     type,
//     title: label,
//     isLeaf: type === 'item'
//   };
// }

const items = reactive([
  // getItem('一级分组', 'grp', null, [getItem('Option 13', '13'), getItem('Option 14', '14')], 'group'),
]);
const baseDir = 'D:/nc_sync/';
//然后，使用axios实例来发送请求
http.get('files?dirPath=' + baseDir).then((res) => {
  const itemsbase = res.data
  items.push(
      ...itemsbase.map(item => {
          return item
      })
  )
  console.log(items)
})
// 获取文件内容
// app.get('/fileContent', (req, res) => {
//     const filePath = req.query.filePath;
//     try {
//         const content = fs.readFileSync(filePath, 'utf8');
//         res.json({ content });
//     } catch (error) {
//         res.status(500).json({ error: error.message });
//     }
// });


</script>
<style>
.ProseMirror {
  font-family: "Open Sans","Clear Sans", "Helvetica Neue", Helvetica, Arial, 'Segoe UI Emoji', sans-serif;
  font-size: 16px;
  line-height: 25.6px;
 }
 .toastui-editor-contents {
   font-family: "Open Sans","Clear Sans", "Helvetica Neue", Helvetica, Arial, 'Segoe UI Emoji', sans-serif;
   font-size: 16px;
   line-height: 25.6px;
}
.sidebar {
  width: 200px;
  height: 100%;
  float: left;
  background-color: #f5f5f5;
  border-right: 1px solid #e5e5e5;
  padding: 20px;
  z-index: 9999;
}
.content {
  margin-left: 200px;
  /* padding: 20px; */
}
.toastui-editor-contents h3 {
  margin: 25px 0;
}
.toastui-editor-defaultUI {
  border: 0;
  border-left: 1px solid #dadde6;
}
.toastui-editor-defaultUI-toolbar {
  background-color: #fff;
}
.sidebar {
      position: fixed;
      right: 0;
      top: 0;
      width: 200px;
      height: 100%;
      background-color: #f5f5f5;
      border-right: 1px solid #e5e5e5;
      padding: 20px;
    }
    #editor {
      margin-right: 200px;
    }
    #editor img {
      max-height: 350px;
    }
.toastui-editor-contents *:not(table) {
  line-height: 1.9em;
}
</style>